package com.hifar.test.entrust.render;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.data.ByteArrayPictureRenderData;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.style.PictureStyle;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.hifar.abi.utils.minio.MinioUtils;
import com.hifar.enums.ReportTypeEnum;
import com.hifar.fw.json.JsonUtils;
import com.hifar.fw.utils.bean.BusiRequest;
import com.hifar.fw.utils.id.IdUtils;
import com.hifar.fw.utils.lang.NumberUtils;
import com.hifar.idm.util.ConvertPdfUtil;
import com.hifar.oldPlatform.utils.SysCommonUtil;
import com.hifar.plat.AopOption.DictModel;
import com.hifar.plat.baseModal.service.IBaseSysDictClassifyService;
import com.hifar.plat.dept.pojo.BaseOrgDeptPlat;
import com.hifar.plat.dept.service.IBaseOrgDeptPlatService;
import com.hifar.plat.user.pojo.BaseOrgUserPlat;
import com.hifar.plat.user.service.IBaseOrgUserService;
import com.hifar.plugins.SignRenderPolicy;
import com.hifar.plugins.TableImgRenderPolicy;
import com.hifar.plugins.TimeRenderPolicy;
import com.hifar.plugins.model.TableImgRenderPolicyModel;
import com.hifar.sys.MinioUtil;
import com.hifar.test.entrust.constant.QrDataConsts;
import com.hifar.test.entrust.model.EntrustPieceQrData;
import com.hifar.test.entrust.model.EntrustProjectQrData;
import com.hifar.test.entrust.model.EntrustQRData;
import com.hifar.test.entrust.model.QrData;
import com.hifar.test.entrust.pojo.HfEnvEntrust;
import com.hifar.test.entrust.pojo.HfEnvPiece;
import com.hifar.test.entrust.pojo.HfEnvProject;
import com.hifar.test.entrust.service.IHfEnvEntrustService;
import com.hifar.test.entrust.service.IHfEnvPieceService;
import com.hifar.test.entrust.service.IHfEnvProjectService;
import com.hifar.test.template.pojo.HfEnvTemplate;
import com.hifar.test.template.service.IHfEnvTemplateService;
import com.hifar.utils.FileUtil;
import com.hifar.utils.QRCodeUtil;
import com.hifar.utils.ToolKit;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.Base64Utils;

import java.io.File;
import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhuWeiWei
 * @description 委托单二维码模板渲染
 * @date 2025/1/10 15:38
 */
@Component
public class HfEnvEntrustQrRender {

    @Autowired
    private IHfEnvTemplateService envTemplateService;
    @Autowired
    private IHfEnvEntrustService envEntrustService;
    @Autowired
    private IHfEnvPieceService pieceService;
    @Autowired
    private IHfEnvProjectService projectService;
    @Autowired
    private IBaseOrgUserService baseOrgUserService;
    @Autowired
    private IBaseOrgDeptPlatService baseOrgDeptPlatService;
    @Autowired
    private IBaseSysDictClassifyService sysDictClassifyService;


    public String renderReport(String entrustId) {
        HfEnvTemplate reportTemplate = envTemplateService.getTemplateByType(ReportTypeEnum.ENV_QR_ENTRUST);
        Assert.notNull(reportTemplate, "二维码生成模板文件不存在!");
        String tempPath = FileUtil.getTempPath();
        String templateLocalPath = tempPath + File.separator + IdUtils.uuid32() + ".docx";
        String tempPdfPath = null;
        File tempWordFile = null;
        try {
            String templatePath = reportTemplate.getTemplatePath();
            String wordObjectName = "hifar/idm/" + entrustId + "QR.docx";
            String pdfObjectName = "hifar/idm/" + entrustId + "QR.pdf";
            MinioUtil.downloadFile(MinioUtil.PRE_DEFAULT, templatePath, templateLocalPath);
            Map<String, Object> pageData = this.packageData(entrustId);
            HfEnvEntrust hfEnvEntrust = envEntrustService.getById(entrustId);
            Integer secretLevel = hfEnvEntrust.getSecretLevel();

            tempWordFile = this.render(new File(templateLocalPath), pageData);
            tempPdfPath = ConvertPdfUtil.wordToPdf(tempWordFile.getAbsolutePath());
            MinioUtils.uploadLocalFileToMinio(MinioUtil.PRE_DEFAULT, wordObjectName, tempWordFile.getAbsolutePath());
            MinioUtils.uploadLocalFileToMinio(MinioUtil.PRE_DEFAULT, pdfObjectName, tempPdfPath, "application/pdf");

            UpdateWrapper<HfEnvEntrust> testUpdateWrapper = new UpdateWrapper<>();
            testUpdateWrapper.lambda()
                    .set(HfEnvEntrust::getQrPdfPath, pdfObjectName)
                    .eq(HfEnvEntrust::getId, entrustId);
            envEntrustService.update(testUpdateWrapper);
            return MinioUtil.getFullFilePaths(MinioUtil.PRE_DEFAULT, pdfObjectName, secretLevel);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("生成失败!");
        } finally {
            if (new File(templateLocalPath).exists()) {
                new File(templateLocalPath).delete();
            }
            if (Objects.nonNull(tempWordFile)) {
                tempWordFile.delete();
            }
            if (Objects.nonNull(tempPdfPath)) {
                new File(tempPdfPath).delete();
            }
        }
    }

    private File render(File templateFile, Map<String, Object> data) throws Exception {
        ConfigureBuilder builder = Configure.builder();
        String tempPath = FileUtil.getTempPath();
        String tempWordPath = tempPath + File.separator + IdUtils.uuid32() + ".docx";

        // < 注册为表格渲染
        LoopRowTableRenderPolicy loopRowTableRenderPolicy = new LoopRowTableRenderPolicy();
        TimeRenderPolicy timeRenderPolicy = new TimeRenderPolicy("yyyy年MM月dd日", true);
        TimeRenderPolicy timeRenderPolicy2 = new TimeRenderPolicy("yyyy/MM/dd", true);
        SignRenderPolicy autographRenderPolicy = new SignRenderPolicy(60, 25);// 电子签名渲染
        SignRenderPolicy signatureRenderPolicy = new SignRenderPolicy(60, 60);// 电子签章渲染

        TableImgRenderPolicy tableImgRenderPolicy = new TableImgRenderPolicy(QrDataConsts.PAGE_ROW_QR_SIZE);

        builder.addPlugin(':', timeRenderPolicy);
        builder.addPlugin('-', timeRenderPolicy2);
        builder.addPlugin('<', loopRowTableRenderPolicy);
        builder.addPlugin('$', autographRenderPolicy);
        builder.bind("tableImgList", tableImgRenderPolicy);
        // 日期渲染插件配置
        Configure.ClearHandler clearHandler = new Configure.ClearHandler();
        builder.useSpringEL(false);
        builder.setValidErrorHandler(clearHandler);
        Configure configure = builder.build();
        XWPFTemplate
                .compile(templateFile.getPath(), configure)
                .render(data)
                .writeAndClose(new FileOutputStream(tempWordPath));
        return new File(tempWordPath);
    }

    private Map<String, Object> packageData(String entrustId) {
        Map<String, Object> dataMap = new HashMap<>();
        HfEnvEntrust envEntrust = envEntrustService.getById(entrustId);
        Assert.notNull(envEntrust, "数据不存在!");
        List<HfEnvPiece> entrustPieceList = pieceService.listByEntrustId(entrustId);
        List<HfEnvProject> entrustProjectList = projectService.listByEntrustId(entrustId);
        String entrustCode = envEntrust.getEntrustCode();
        EntrustQRData entrustQRData = new EntrustQRData();
        BeanUtils.copyProperties(envEntrust, entrustQRData);
        String entrustCustId = envEntrust.getEntrustCustId();
        String entrustUserId = envEntrust.getEntrustUserId();

        BaseOrgUserPlat baseOrgUserPlat = baseOrgUserService.getById(entrustUserId);

        String entrustUserCode = Optional.ofNullable(baseOrgUserPlat)
            .map(BaseOrgUserPlat::getUserCode).orElse(null);
        entrustQRData.setEntrustUserCode(entrustUserCode);

        String entrustCustCode = Optional.ofNullable(baseOrgDeptPlatService.getById(entrustCustId))
            .map(BaseOrgDeptPlat::getDeptCode).orElse(null);
        entrustQRData.setEntrustCustCode(entrustCustCode);

        List<EntrustPieceQrData> entrustPieceQrDataList = entrustPieceList.stream()
                .map(item -> {
                    EntrustPieceQrData entrustPieceQrData = new EntrustPieceQrData();
                    BeanUtils.copyProperties(item, entrustPieceQrData);
                    return entrustPieceQrData;
                }).collect(Collectors.toList());

        List<EntrustProjectQrData> entrustProjectQrDataList = entrustProjectList.stream()
                .map(item -> {
                    EntrustProjectQrData entrustProjectQrData = new EntrustProjectQrData();
                    BeanUtils.copyProperties(item, entrustProjectQrData);
                    return entrustProjectQrData;
                }).collect(Collectors.toList());
        entrustQRData.setPieceList(entrustPieceQrDataList);
        entrustQRData.setProjectList(entrustProjectQrDataList);
        String entrustQrData = JsonUtils.toJson(entrustQRData);
        int qrDataSize = NumberUtils.parseInt(SysCommonUtil.getSysConfigValueByKey(new BusiRequest()
                , QrDataConsts.QR_DATA_SIZE_CODE)
                , QrDataConsts.QR_DATA_SIZE);
        String entrustQrBase64Data = Base64Utils.encodeToString(entrustQrData.getBytes(StandardCharsets.UTF_8));
        List<String> qrDataList = ToolKit.splitStr(entrustQrBase64Data, qrDataSize);

        final int qrCount = qrDataList.size();

        String pieceNos = entrustPieceList.stream()
                .map(HfEnvPiece::getPieceNo)
                .collect(Collectors.joining(","));

        dataMap.put("entrustCode", entrustCode);
        dataMap.put("subjectName", envEntrust.getSubjectName());
        dataMap.put("subjectNo", envEntrust.getSubjectNo());
        dataMap.put("entrustTime", envEntrust.getEntrustTime());
        dataMap.put("entrustCust", envEntrust.getEntrustCust());
        dataMap.put("entrustUserName", envEntrust.getEntrustUserName());
        dataMap.put("entrustUserPhone", envEntrust.getEntrustUserPhone());
        dataMap.put("pieceNum", entrustPieceList.size());
        dataMap.put("predictFinishTime", envEntrust.getPredictFinishTime());
        dataMap.put("testPropertyCode", envEntrust.getTestPropertyCode());

        String testPropertyName = sysDictClassifyService.queryDictItemsByCode("hf_env_test_property")
            .stream()
            .filter(item -> item.getValue().equals(envEntrust.getTestPropertyCode()))
            .findFirst()
            .map(DictModel::getText)
            .orElse("");

        dataMap.put("testPropertyName", testPropertyName);
        dataMap.put("remarks", envEntrust.getRemarks());
        dataMap.put("pieceNos", pieceNos);
        dataMap.put("projectList", entrustProjectList);
        dataMap.put("qrCodeNum", qrDataList.size());

        List<TableImgRenderPolicyModel> tableImgRenderPolicyModelList = new ArrayList<>();


        int qrSeq = 1;
        for (String dataText : qrDataList) {
            QrData qrData = new QrData();
            qrData.setData(dataText);
            qrData.setTotal(qrCount);
            qrData.setCurrent(qrSeq);
            qrData.setEntrustCode(entrustCode);
            String qrDataText = JsonUtils.toJson(qrData);

            byte[] qrImgBytes = QRCodeUtil.generateQRCodeImageBts(qrDataText
                    , QrDataConsts.QR_CODE_WIDTH, QrDataConsts.QR_CODE_HEIGHT);
            TableImgRenderPolicyModel tableImgRenderPolicyModel = new TableImgRenderPolicyModel();
            tableImgRenderPolicyModel.setTitle(String.valueOf(qrSeq));
            PictureRenderData pictureRenderData = new ByteArrayPictureRenderData(qrImgBytes);

            PictureStyle pictureStyle = new PictureStyle();

            pictureStyle.setWidth(QrDataConsts.QR_CODE_WIDTH);
            pictureStyle.setHeight(QrDataConsts.QR_CODE_HEIGHT);

            pictureRenderData.setPictureStyle(pictureStyle);
            tableImgRenderPolicyModel.setImgData(pictureRenderData);
            tableImgRenderPolicyModelList.add(tableImgRenderPolicyModel);
            qrSeq++;
        }
        dataMap.put("tableImgList", tableImgRenderPolicyModelList);
        return dataMap;
    }


}
